#pragma once

#include "symboltable.h"
#include "parsetree.h"
#include "operators.h"
#include "generatemodulecode.h"

#include <string>
#include <vector>
#include <map>

#include "generate_designator.h"
#include "generate_declaration.h"
#include "generate_expression.h"
#include "generate_statement.h"

using std::vector;
using std::string;
using std::map;

using namespace Thinder;

// C Code Generator

typedef map<ParseTree::Name, string> NameStringMap;

string generateCode(ParseTree::Thinder &thinder, SymbolTable &symbolTable, OperatorMap &m);
ParseTree::Name toName(string name);
string generateType(ParseTree::Name ns, ParseTree::Type &type);
string generateFormPars(ParseTree::Name ns, vector<ParseTree::FormPar> &formPars);
string generateFormPar(ParseTree::Name ns, ParseTree::FormPar &formPar);
bool existsInNamespace(ParseTree::Name ns, ParseTree::Name ident);
ParseTree::Name namespaceLookupFQN(ParseTree::Name ns, ParseTree::Identifier ident);
ParseTree::Name namespaceLookupFQN(ParseTree::Name ns, ParseTree::Name ident);
Symbol namespaceLookup(ParseTree::Name ns, ParseTree::Name ident);
Symbol namespaceLookup(ParseTree::Name ns, ParseTree::Identifier ident);
ParseTree::Name namespaceLookupFQN(SymbolTable &s, ParseTree::Name ns, ParseTree::Name ident);
ParseTree::Name getThisClass(ParseTree::Name ns);
bool isFieldOfClass(ParseTree::Name ns, ParseTree::Identifier ident);
bool isFieldOfClass(ParseTree::Name ns, ParseTree::Name ident);
bool isFieldOfThisClass(ParseTree::Name ns, ParseTree::Identifier ident);
bool isFieldOfThisClass(ParseTree::Name ns, ParseTree::Name ident);
bool isMethodOfClass(ParseTree::Name ns, ParseTree::Identifier ident);
bool isMethodOfClass(ParseTree::Name ns, ParseTree::Name ident);
bool isMethodOfThisClass(ParseTree::Name ns, ParseTree::Identifier ident);
bool isMethodOfThisClass(ParseTree::Name ns, ParseTree::Name ident);
ParseTree::Name getDominantOperatorOverload(ParseTree::Name ns, ParseTree::Expression &expr);
ParseTree::Type getTypeOfExpression(ParseTree::Name ns, ParseTree::Expression &expr);
Symbol findInternal(string internal);
ParseTree::Name findSymbolName(Symbol symbol);

extern SymbolTable symbolTable;
extern OperatorMap operatorMap;
extern string variables;
extern string classprototypes;
extern string prototypes;
extern NameStringMap functions;
extern NameStringMap classes;
extern NameStringMap freeVars;
extern string beforeStatement;
extern string afterStatement;
extern vector<ParseTree::Name> functionStack;


